import { HttpException, HttpStatus, Inject, Injectable, Logger } from '@nestjs/common';
import { Prisma } from '@prisma/client'
import { PrismaService } from '../prisma/prisma.service';
import { RedisService } from '../redis/redis.service';
import { RegisterUserDto } from './dto/register-user.dto';
import { generateCaptcha, generateTimeStamp, generateUUID, md5 } from '@/common/util'
import { LoginUserDto } from './dto/login-user.dto';
import { ResultData } from '@/common/util/result';
import { JwtService } from '@nestjs/jwt';
import { Prefix } from '@/common/enum'
import { ConfigService } from '@nestjs/config';
import { UpdatePasswordDto } from './dto/update-password.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UserService {
    @Inject()
    private jwtService: JwtService
    @Inject()
    private prisma: PrismaService

    @Inject()
    private redisService: RedisService

    private logger = new Logger();

    constructor(private readonly configService: ConfigService) { }

    async generateSvgCaptcha(prefix: string) {
        const captcha = generateCaptcha()
        const base64Svg = Buffer.from(captcha.data).toString('base64');
        const uuid = generateUUID()
        await this.redisService.set(`${prefix}${uuid}`, captcha.text, 60 * 2)
        return { uuid, img: `data:image/svg+xml;base64,${base64Svg}` }
    }
    async register(user: RegisterUserDto) {
        // const captcha = await this.redisService.get(`${Prefix.registerCaptcha}${user.email}`)
        // if (!captcha) {
        //     throw new HttpException('验证码已失效', HttpStatus.BAD_REQUEST)
        // }
        // if (captcha !== user.captcha) {
        //     throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST)
        // }
        const foundUser = await this.prisma.user.findUnique({
            where: {
                username: user.username
            }
        })
        if (foundUser) {
            throw new HttpException('用户已存在', HttpStatus.BAD_REQUEST)
        }
        try {
            return await this.prisma.user.create({
                data: {
                    username: user.username,
                    password: md5(user.password),
                    email: user.email,
                    nickName: user.nickName
                },
                select: {
                    id: true,
                    username: true,
                    nickName: true,
                    email: true,
                    headPic: true,
                    createTime: true
                }
            })
        } catch (e) {
            this.logger.error(e, UserService)
            return null
        }


    }
    async login(loginUserDto: LoginUserDto) {
        console.log(loginUserDto);
        let foundUser = await this.prisma.user.findUnique({
            where: {
                username: loginUserDto.username
            },
        })
        if (!foundUser) {
            throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
        }
        if (foundUser.password !== md5(loginUserDto.password)) {
            throw new HttpException('用户名或密码错误', HttpStatus.BAD_REQUEST);
        }

        const loggedUser = await this.redisService.get(`${Prefix.loginToken}${foundUser.id}`)
        if (loggedUser) {
            await this.redisService.del(`${Prefix.loginToken}${foundUser.id}`);
        }
        const iat = generateTimeStamp()
        const token = this.createToken({ id: foundUser.id, iat })
        this.redisService.set(`${Prefix.loginToken}${foundUser.id}`, JSON.stringify({ ...foundUser, iat, token }), this.configService.get('jwt.expiresin'))
        return ResultData.ok(token, '登录成功');
    }
    async logout(id: number) {
        await this.redisService.del(`${Prefix.loginToken}${id}`)
        return ResultData.ok(null, '退出成功')
    }

    async update(id: number, updateUserDto: UpdateUserDto) {

        try {
            await this.prisma.user.update({
                where: {
                    id
                },
                data: {
                    ...updateUserDto
                }
            })
            return ResultData.ok(null, '修改成功')
        } catch (e) {
            this.logger.error(e, UserService)
            return ResultData.fail(500, '修改失败')
        }
    }
    async updatePassword(id: number, passwordDto: UpdatePasswordDto) {
        const { email } = await this.findUserById(id)
        const updateCaptcha = await this.redisService.get(`${Prefix.updateCaptcha}${email}`)
        if (!updateCaptcha) throw new HttpException('验证码已失效', HttpStatus.BAD_REQUEST)

        if (updateCaptcha !== passwordDto.captcha) throw new HttpException('验证码不正确', HttpStatus.BAD_REQUEST)

        try {
            await this.prisma.user.update({
                where: {
                    id
                },
                data: {
                    password: md5(passwordDto.password)
                }
            })
            return ResultData.ok(null, '修改成功')
        } catch (e) {
            this.logger.error(e, UserService)
            return ResultData.fail(500, '修改失败')
        }
    }

    async findUserById(id: number) {
        return await this.prisma.user.findUnique({
            where: {
                id
            },
            select: {
                id: true,
                username: true,
                nickName: true,
                email: true,
                createTime: true,
                updateTime: true,
                headPic: true
            },
        });
    }


    /**
         * 从数据声明生成令牌
         *
         * @param payload 数据声明
         * @return 令牌
         */
    createToken(payload: { id: number, iat: number }): string {
        return this.jwtService.sign(payload);
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    parseToken(token: string) {
        try {
            if (!token) return null;
            const payload = this.jwtService.verify(token.replace('Bearer ', ''));
            return payload;
        } catch (error) {
            console.log('信息错误');
            return null;
        }
    }
}
